/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package dameki.output;

import dameki.core.CheckPlayer;
import dameki.core.GlobalVars;
import dameki.game.GameMove;
import dameki.game.Stone;
import dameki.game.player.Player;
import java.awt.Dimension;
import java.awt.DisplayMode;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;

/**
 *
 * @author martnath
 */
public class SwingGUI extends Player implements IGUI, MouseListener, MouseMotionListener {

    private int width = 606;
    private int height = 629;
    private JFrameExt frame;
    private boolean input = false;
    private GameMove nextMove;
    private Stone[][] tempfield;
    private Stone stoneBackup;
    private int mousePressedX, mousePressedY, carryXpos, carryYpos;
    private boolean mousepressed = false;

    public SwingGUI(boolean color) {
        super(color);

        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        GraphicsDevice gs = ge.getDefaultScreenDevice();
        GraphicsDevice gd = gs;
        DisplayMode dm = gd.getDisplayMode();

        frame = new JFrameExt("Dame - von Nathalie Martin, Tobi König und Samuel Schneider");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(null);
        frame.setBounds(dm.getWidth() / 2 - width / 2, dm.getHeight() / 2 - height / 2, width, height);
        frame.setSize(width, height);
        frame.setMinimumSize(new Dimension(width, height));
        frame.pack();        
        frame.setResizable(false);
        
        //frame.setComponentZOrder(background, 1);
        frame.setVisible(true);

        frame.addMouseListener(this);
        frame.addMouseMotionListener(this);
    }

    @Override
    public GameMove[] move(Stone[][] field) {
        Stone[][] fieldsave = CheckPlayer.getNewFieldState(null, field);
        int[] pos =  null;
        Stone save = null;
        boolean iterate = true;
        while (iterate) {
            if(input){
                if(pos==null && save ==null){
                    pos =  getTempPosOfStone(nextMove.getStone(), fieldsave);
                    save = nextMove.getStone();
                }else{
                    fieldsave[pos[0]][pos[1]]=save;                    
                }
                if(CheckPlayer.checkMove(nextMove, pos, color, fieldsave)){
                    iterate = false;
                }else{
                    System.out.println("No valid Move!");                    
                    update(fieldsave);
                    input = false;
                }
            }
            try {
                Thread.sleep(25);
            } catch (InterruptedException ex) {
                Logger.getLogger(SwingGUI.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        //check if there are jumps possible
        ArrayList<GameMove> p_jumps = CheckPlayer.getPossibleJumps(this, fieldsave);
        //if(p_jumps != null){
        if(false){
            boolean jump = false;
            for(GameMove m:p_jumps){
                if(m.equals(nextMove)){
                    jump = true;
                    break;
                }                    
            }
            if(jump){
                Stone[][] newfield = CheckPlayer.getNewFieldState(nextMove, fieldsave);
                if(CheckPlayer.getPossibleJumps(this, newfield)!=null){
                    System.out.println("You need to perform another jump!");
                    ArrayList<GameMove> oldmoves = new ArrayList<>();
                    oldmoves.add(nextMove);
                    
                    input = false;
                    update(newfield);
                    addArrayToList(oldmoves, move(newfield));
                    
                    input = false;
                    return ListToArray(oldmoves);
                }else{
                    input = false;                    
                    return new GameMove[]{nextMove};
                }
            }else{
                System.out.println("You need to perform a jump!");
                update(fieldsave);
                input = false;
                return move(fieldsave);
            }
        }else{
            input = false;
            return new GameMove[]{nextMove};
        }
    }

    @Override
    public void update(Stone[][] field) {        //public boolean mouseDown(Event e, int x, int y){return true;}
        tempfield = field;
        
        frame.setField(tempfield);
        frame.repaint();
        //waitForAnyKey();
    }
    
    /*
     * private void waitForAnyKey() {
     *
     * final CountDownLatch latch = new CountDownLatch(1); KeyEventDispatcher
     * dispatcher = new KeyEventDispatcher() { // Anonymous class invoked from
     * EDT
     *
     * @Override public boolean dispatchKeyEvent(KeyEvent e) { try { //if
     * (e.getKeyCode() == KeyEvent.VK_SPACE) Thread.sleep(100); } catch
     * (InterruptedException ex) {
     * Logger.getLogger(SwingGUI.class.getName()).log(Level.SEVERE, null, ex); }
     * latch.countDown(); return false; } };
     * KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(dispatcher);
     * try { latch.await(); // current thread waits here until countDown() is
     * called } catch (InterruptedException ex) {
     * Logger.getLogger(SwingGUI.class.getName()).log(Level.SEVERE, null, ex); }
     * KeyboardFocusManager.getCurrentKeyboardFocusManager().removeKeyEventDispatcher(dispatcher);
     * }
     */

    @Override
    public void animate(GameMove[] move)
    {
        if(move==null)
        {
            return;
        }
        
        if(move[0].getStone().getColor() == GlobalVars.COLOR_W)
        {
            return;
        }
            
        boolean isDame = tempfield[move[0].getStone().getPosY()][move[0].getStone().getPosX()].IsDame();
        tempfield[move[0].getStone().getPosY()][move[0].getStone().getPosX()] = null;
        update(tempfield);
        
        for(int i=0; i<move.length; i++)
        {
            //isDame = move[0].getStone().IsDame();
            
            int x1;
            int y1;
            
            if(i == 0)
            {
                x1 = move[i].getStone().getPosX();
                y1 = move[i].getStone().getPosY();
            }
            else
            {
                x1 = move[i - 1].getPosX();
                y1 = move[i - 1].getPosY();
            }
            
            int x2 = move[i].getPosX();
            int y2 = move[i].getPosY();
                    
            Stone s = new Stone(!this.color, 0, 0);
            s.setDame(isDame);                

            int xtween = x2 - x1;

            y1 = 7 - y1;
            y2 = 7 - y2;

            int ytween = y2 - y1;

            for(int time=0; time<=100; time++)
            {
                float xpos = (float)x1 + (float)xtween * ((float)time/100);
                float ypos = (float)y1 + (float)ytween * ((float)time/100);

                s.setPosX((int)(xpos * 75));
                s.setPosY((int)(ypos * 75));
                frame.setAnimatedStone(s);
                frame.repaint();

                try {
                    Thread.sleep(25);
                } catch (InterruptedException ex) {
                    Logger.getLogger(SwingGUI.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
            frame.setAnimatedStone(null);
            frame.repaint();
            
        }
    }
    
    @Override
    public void mouseClicked(MouseEvent e) 
    {
    }

    @Override
    public void mousePressed(MouseEvent e) 
    {
        mousepressed = true;

        int x = e.getX() - 3;
        x = x / 75;
        int y = e.getY() - 25;
        y = 600 - y;
        y = y / 75;

        mousePressedX = x;
        mousePressedY = y;

        stoneBackup = tempfield[y][x];
        tempfield[y][x] = null;

        update(tempfield);

        System.out.println(x);
        System.out.println(y);
        
        nextMove = new GameMove(stoneBackup, -1, -1);
    }

    @Override
    public void mouseReleased(MouseEvent e)
    {
        mousepressed = false;
        frame.setAnimatedStone(null);

        int x = e.getX() - 3;
        x = x / 75;
        int y = e.getY() - 25;
        y = 600 - y;
        y = y / 75;

        System.out.println(x);
        System.out.println(y);

        if (
                ((nextMove.getStone().getPosX() == x) && (nextMove.getStone().getPosY() == y)) || //Stone was not moved
                (tempfield[y][x] != null) || //Targetspace is not empty
                (Math.abs(nextMove.getStone().getPosX() - x) == 0) //Stone was not moved diagonally
                
                )
                
        {
            //Something is wrong abort !          
            tempfield[mousePressedY][mousePressedX] = stoneBackup;
            update(tempfield);

            return;
        }

        if (nextMove != null) 
        {
            nextMove.setPosX(x);
            nextMove.setPosY(y);

            input = true;        
        }
    }

    @Override
    public void mouseEntered(MouseEvent e) 
    {
    }

    @Override
    public void mouseExited(MouseEvent e) 
    {
    }

    @Override
    public void mouseDragged(MouseEvent e) 
    {
        if (mousepressed) {

            carryXpos = e.getX() - 75 / 2;
            carryYpos = e.getY() - 75 / 2;

            if(stoneBackup != null) 
            {
                Stone s = new Stone(this.color, carryXpos, carryYpos);
                s.setDame(stoneBackup.IsDame());
                frame.setAnimatedStone(s);
                frame.repaint();
            }
        }
    }

    @Override
    public void mouseMoved(MouseEvent e) 
    {
    }
    
    private void addArrayToList(ArrayList<GameMove> list,GameMove[] array){
        for(int x=0;x<array.length;x++){
            list.add(array[x]);
        }
    }
    
    private GameMove[] ListToArray(ArrayList<GameMove> list){
        GameMove[] array = new GameMove[list.size()];
        for(int x=0;x<list.size();x++){
            array[x]=list.get(x);
        }
        return array;
    }
    
    private int[] getTempPosOfStone(Stone s,Stone[][] field){
        for(int y=0;y<field.length;y++){
            for(int x=0;x<field.length;x++){
                if(field[y][x]!=null && field[y][x]==s){
                    return new int[]{y,x};
                }
            }
        }
        return null;
    }
}
